package mnn;

/*
 This program is written by Ahmed Medhat Ahmed
 Egypt
 Alexandria Universty
 Faculty of Science
 Computer Science
 7-7-2007
 a.medhat.cs@gmail.com
 ama_compsc@yahoo.com
 */
import java.util.Random;

public class Train {

	private int input;
	private int output;
	private int trainc;
	private int hiddenlayer;
	private int hiddenneurons;
	private double learnrate;
	private double momentumrate;
	private Random rand;

	private double out_arr[][];

	private String outstring;

	private ANN neuro;

	public Train() {
	}

	public Train(int in, int out, int hl, int hn, double lr, double mr, int tc) {
		input = in;
		output = out;
		trainc = tc;
		hiddenlayer = hl;
		hiddenneurons = hn;
		learnrate = lr;
		momentumrate = mr;

		rand = new Random(0);

		neuro = new ANN(input, output, hiddenlayer, hiddenneurons, learnrate,
				momentumrate, rand);

		out_arr = new double[out][out];
	}

	/*
	 * public static void main(String args[]) { train = new Train();
	 * train.start(); }
	 */

	public void getDim4(int[] Dim4) {
		neuro.func2(Dim4);
	}

	public void getweights(double[][][] weight, int[] Dim4) {
		double x[][][];// which will contain the waites
		int con[] = new int[1];// connectionlayers
		int nlayer[] = new int[1];// neuronlayers
		int maxneur[] = new int[1];// maxneurons
		int ncount[]; // neuroncount[neuronlayer]

		neuro.func1(con, nlayer, maxneur);

		x = new double[con[0]][maxneur[0]][maxneur[0]];
		neuro.getwaites(x);
		ncount = new int[nlayer[0]];
		neuro.func2(ncount);
		neuro.func2(Dim4);

		for (int i = 0; i < con[0]; i++) {
			for (int j = 0; j < ncount[i]; j++) { // no of in nodes
				for (int k = 0; k < ncount[i + 1]; k++) {// out nodes
					weight[i][j][k] = x[i][j][k];
				}
			}
		}
	}

	public void getweightsDim(int[] Dim) {
		int con[] = new int[1];// connectionlayers
		int nlayer[] = new int[1];// neuronlayers
		int maxneur[] = new int[1];// maxneurons

		neuro.func1(con, nlayer, maxneur);

		Dim[0] = con[0];
		Dim[1] = nlayer[0];
		Dim[2] = maxneur[0];
	}

	public void setwaites(double[][][] weight) {
		neuro.setwaites(weight);
	}

	public void start(int in_array[][][], int out_array[][]) {
		int i, j, k;
		int count1 = 0;
		int count2 = 0;
		double error = 0.0;
		double errorsum = 0.0;
		double avg = 0.0;

		double Din_array[][][] = new double[output][trainc][input];
		double Dout_array[][] = new double[output][output];

		// converting from integer to double
		for (i = 0; i < output; i++)
			for (j = 0; j < trainc; j++)
				for (k = 0; k < input; k++)
					Din_array[i][j][k] = Double.valueOf(in_array[i][j][k]);
		for (i = 0; i < output; i++)
			for (j = 0; j < output; j++)
				Dout_array[i][j] = Double.valueOf((out_array[i][j]));// .toString());

		outstring = "";

		for (i = 0; i < output; i++)// number of classes
		{
			outstring += "\n\n\n Training NN Calss number " + (i + 1);
			for (j = 0; j < trainc; j++)// number of training cases
			{
				if ((j % 3) != 0) {
					count1++;
					out_arr[i] = neuro.getResult(Din_array[i][j]);
					for (k = 0; k < output; k++) {
						error = (Dout_array[i][k] - out_arr[i][k]) == 0.0 ? 0.0
								: 1.0;
						errorsum += error;
					}
				}
			}
			outstring += "\n\n";

			for (int a = 1; a <= 10; a++) {
				// training per cycle
				for (int b = 1; b <= 100; b++) {
					for (j = 0; j < trainc; j++)// number of training cases
					{
						if ((j % 3) != 0) {
							neuro.Train(Din_array[i][j], Dout_array[i]);
						}
					}
					for (j = 0; j < trainc; j++) {
						if ((j % 3) != 0) {
							out_arr[i] = neuro.getResult(Din_array[i][j]);
							for (k = 0; k < output; k++) {
								error = (Dout_array[i][k] - out_arr[i][k]) == 0.0 ? 0.0
										: 1.0;
								errorsum += error;
							}
						}
					}
					avg = errorsum / count1;
					errorsum = 0.0;
				}// b
				outstring += "\n\n Traninig Data at Iteration # " + (a * 100);
				outstring += "\n\n Classification error with  PATHO  =  " + avg;
				// System.out.println(i*10+" "+avg);
				/************************** Test Data *****************************************/
				for (j = 0; j < trainc; j++) {
					count2++;
					out_arr[i] = neuro.getResult(Din_array[i][j]);
					for (k = 0; k < output; k++) {
						error = (Dout_array[i][k] - out_arr[i][k]) == 0.0 ? 0.0
								: 1.0;
						errorsum += error;
					}
				}
				avg = errorsum / count2;
				errorsum = 0.0;

				outstring += "\n Process with Testing Data ";
				outstring += "\n Classification error with  PATHO     =  "
						+ avg;
				outstring += "\n ******************************************* ";
			} // a
			outstring += "\n\n traning data = " + count1 + " Testing data = "
					+ count2;
		}
	}// start()

	public String train_info() {
		return outstring;
	}
}
